package com.travel.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.travel.common.vo.MemberRespVo;
import com.travel.member.dao.MemberSignDao;
import com.travel.member.service.MemberSignService;
import com.travel.member.vo.SignVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static com.travel.common.constant.AuthServerConstant.LOGIN_USER;

@Service
public class MemberSignServiceImpl implements MemberSignService {

    // 用于获取登录的用户
    public static ThreadLocal<MemberRespVo> loginUser = new ThreadLocal<>();

    @Autowired
    MemberSignDao memberSignDao;

    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * 获取本月该用户有签到的日期
     * @return
     */
    @Override
    public List<SignVo> signRecord() {
        //1. 获取当前登录用户
        String s = redisTemplate.opsForValue().get(LOGIN_USER);
        MemberRespVo memberRespVo = JSON.parseObject(s,MemberRespVo.class);
        Integer userId = memberRespVo.getMemberId().intValue();
        //2. 获取日期
        LocalDateTime now = LocalDateTime.now();
        //3. 拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyy/MM"));
        String key = "signInfo:"+ userId + keySuffix;
        //4. 获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //5. 获取本月截至今天为止的所有的签到记录，返回的是一个十进制数组  BITFIELD signInfo:1:2023/12 u6 0
        //获取从第一天到今天为止的记录  返回为十进制
        // u:无符号  dayOfMonth:获取到今天为止的天数  0:从第一天开始获取
        List<Long> result = redisTemplate.opsForValue().bitField(
                key,
                BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
        if(result == null || result.isEmpty()){
            return null;
        }

        //6. 遍历封装为SignVo的list
        List<SignVo> signVoList = new ArrayList<>();

        Calendar calendar = Calendar.getInstance();

        // 获取有签到的日期
        for (int i=0;i<dayOfMonth;i++){
            Boolean bit = redisTemplate.opsForValue().getBit(key, i);
            if(bit){
                Date currentDate = calendar.getTime(); // 当前日期
                calendar.set(Calendar.DATE, i+1); // 设置日期

                SignVo signVo = new SignVo();
                signVo.setTime(calendar.getTime());

                calendar.setTime(currentDate); // 恢复当前日期

                signVoList.add(signVo);
            }
        }

        System.out.println("signVoList"+signVoList);
        return signVoList;
    }

    /**
     * 签到
     */
    @Override
    public void sign() {
        //1. 获取当前用户
        String s = redisTemplate.opsForValue().get(LOGIN_USER);
        MemberRespVo memberRespVo = JSON.parseObject(s,MemberRespVo.class);
        Integer userId = memberRespVo.getMemberId().intValue();
        //2. 获取日期
        LocalDateTime now = LocalDateTime.now();
        //3. 拼接key   key:signInfo:userId:2023/12
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyy/MM"));
        String key = "signInfo:"+ userId + keySuffix;
        //4. 获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //5. 写入Redis SETBIT Key offset 1
        redisTemplate.opsForValue().setBit(key,dayOfMonth-1,true);
    }

    /**
     * 统计本月的连续签到次数
     */
    @Override
    public Integer signCount() {
        //1. 获取当前用户
        String s = redisTemplate.opsForValue().get(LOGIN_USER);
        MemberRespVo memberRespVo = JSON.parseObject(s,MemberRespVo.class);
        Integer userId = memberRespVo.getMemberId().intValue();
        //2. 获取日期
        LocalDateTime now = LocalDateTime.now();
        //3. 拼接key   key:signInfo:userId:2023/12
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyy/MM"));
        String key = "signInfo:"+ userId + keySuffix;
        //4. 获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //5. 获取本月截止今天为止的所有的签到记录，返回的是一个十进制的数字 BITFIELD signInfo:1:2023/12 GET u7 0
        //u：无符号     7：获取7位数     0：从0开始获取
        List<Long> result = redisTemplate.opsForValue().bitField(key,
                BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
        if(result == null || result.isEmpty()){
            return null;
        }
        System.out.println("result "+result);
        Long num = result.get(0);
        //6. 循环遍历
        int signCount = 0;
        while(true){
            //6.1 让这个数与1做与运算，得到数字的最后一个bit未  判断这个bit是否为0
            if((num&1) == 0){
                // 如果为0，说明没有签到，结束
                break;
            }else{
                // 如果不为0，说明已签到，计数器+1
                signCount++;
            }
            // 把数字右移一位，抛弃最后一位，继续判断下一个bit位
            num >>>= 1;
        }
        return signCount;
    }

}
